home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / DirectShow / Capture / DVApp / dvapp.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-08  |  64.0 KB  |  1,616 lines

  1. //------------------------------------------------------------------------------
  2. // File: DVApp.cpp
  3. //
  4. // Desc: DirectShow sample code - DV control/capture example.
  5. //
  6. // Copyright (c) 2000-2001 Microsoft Corporation.  All rights reserved.
  7. //------------------------------------------------------------------------------
  8.  
  9. #include <windows.h>
  10. #include <commdlg.h>
  11. #include <commctrl.h>
  12. #include <tchar.h>
  13. #include <dbt.h>
  14. #include <streams.h>
  15. #include <xprtdefs.h> 
  16. #include "CDVGraph.h"
  17. #include "resource.h"
  18.  
  19. // ------------ constants-----------------
  20. #define DV_CAPLIMIT_NONE         10L
  21. #define DV_CAPLIMIT_TIME         11L
  22. #define DV_CAPLIMIT_SIZE         12L
  23.  
  24. #define DV_BYTESPERMSEC          352  //DV captures at 3600K per second (3600 / 1024 == ~3.52)
  25. #define DV_TIMERFREQ             55   //milliseconds between timer ticks
  26. #define DV_BYTES_IN_MEG          1048576L  //(1024 * 1024)
  27.  
  28. // ----------macros-----------------------
  29. #define MBOX(s)                 MessageBox(g_hwndApp, s, APPNAME, MB_OK);
  30.  
  31. // ----------function prototypes----------
  32. BOOL            FInitMain(int nCmdShow);
  33. int             NMsgLoop(void);
  34. BOOL            DV_InitControls(HWND hwnd, HINSTANCE hInst);
  35.  
  36. HRESULT         DV_AppSetup(void);
  37. HRESULT         SetPreviewWindow(void);
  38.  
  39. // UI help functions
  40. void Mark_ToolBar_Button(BOOL bEnableRecord, BOOL bEnableOthers);
  41. void Mark_GraphMode_Menu(HWND hwnd, int idmVal);
  42. void GetSelectedGraphMode( WPARAM wParam, GRAPH_TYPE* pGraphType);
  43.  
  44. // Message Processing Functions
  45. LRESULT CALLBACK    MainWndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
  46. void CALLBACK       DV_TransportCommand_WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
  47. void CALLBACK       DV_GraphModeCommand_WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
  48. BOOL CALLBACK       DV_CapSizeDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
  49. void CALLBACK       DV_DroppedFrameProc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime);
  50. void CALLBACK       DV_TimecodeTimerProc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime);
  51. void CALLBACK       DV_StopRecProc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime);
  52. BOOL CALLBACK       DV_AboutDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
  53. void                DV_DisplayTimecode();
  54. BOOL                DV_SeekATN(void);
  55. BOOL                DV_UpdateTapeInfo(void);
  56. BOOL                DV_RefreshMode(void);
  57.  
  58. // ------------global data----------------
  59.  
  60. // Handles to the windows
  61. HINSTANCE       g_hinst;
  62. HWND            g_hwndApp               = NULL;
  63. HWND            g_hwndTBar              = NULL; 
  64. HWND            g_hwndStatus            = NULL;
  65. HMENU           g_hmenu;
  66.  
  67. // metrics of the windows
  68. int             g_iAppHeight            = DEFAULT_VIDEO_HEIGHT + HEIGHT_EDGE;
  69. int             g_iAppWidth             = DEFAULT_VIDEO_WIDTH  + WIDTH_EDGE;        
  70. int             g_iVWHeight             = DEFAULT_VIDEO_HEIGHT;
  71. int             g_iVWWidth              = DEFAULT_VIDEO_WIDTH;        
  72. DWORD           g_statusHeight          = 0;
  73.  
  74. // device notification globals
  75. PVOID           g_hDevNotify   = NULL;
  76. BOOL            g_bDeviceFound = FALSE;
  77.  
  78. // capture variables
  79. DWORD                   g_dwCaptureLimit        = DV_CAPLIMIT_NONE; //track whether we are using time, disk, or no based capture limits
  80. DWORD                   g_dwDiskSpace           = 120;              //roughly the same
  81. DWORD                   g_dwTimeLimit           = 30;               //default to 30 seconds of capture
  82.  
  83. // graph related variables
  84. CDVGraph*       g_pGraph        = NULL; 
  85. GRAPH_TYPE      g_iGraphType    = GRAPH_PREVIEW;    //need to track the current graph
  86.  
  87. // file names
  88. TCHAR           g_InputFileName[_MAX_PATH]          = {DEFAULT_CAP_FILE_NAME};
  89. TCHAR           g_OutputFileName[_MAX_PATH]         = {DEFAULT_CAP_FILE_NAME};
  90. TCHAR           g_FilterGraphFileName[_MAX_PATH]    = {DEFAULT_FG_FILE_NAME};
  91.  
  92. DWORD           g_CapStartTime          = 0;
  93. BOOL            g_bUseAtnTimer          = FALSE;  //track if we want to constantly update the timer
  94. BOOL            g_bHalfFrameRate        = FALSE;
  95.  
  96.  
  97. // ------------inline functions-------------------
  98. // put the VCR Mode
  99. inline HRESULT DV_PutVcrMode(long Mode)
  100. {
  101.     if(!g_pGraph->m_pIAMExtTransport)
  102.         return S_FALSE;
  103.     return g_pGraph->m_pIAMExtTransport->put_Mode(Mode);
  104.  
  105. // update the status windows with appropriate text
  106. inline LRESULT DV_StatusText(LPCTSTR statusText, UINT nPart)
  107. {
  108.     return SendMessage(g_hwndStatus, SB_SETTEXT, (WPARAM) 0 | nPart, (LPARAM)statusText);
  109.  
  110. //divide the status bar into thirds, and give the middle frame an extra 100 pixels.
  111. inline LRESULT DV_StatusParts(UINT width)
  112. {
  113.     int rg[3];
  114.     rg[0] = (width / 3) - 50;
  115.     rg[1] = ((rg[0]+50) * 2) + 50;
  116.     rg[2] = -1;
  117.     return SendMessage(g_hwndStatus, SB_SETPARTS, 3, (LPARAM)(LPINT) rg);
  118. }    
  119.  
  120.  
  121. /*-------------------------------------------------------------------------
  122. Routine:        WinMain
  123. Purpose:        Program entry point      
  124. Arguments:      Usual
  125. Returns:        Usual
  126. Notes:          Sets up window capabilities, initializes & 
  127.                     creates the required DirectShow interface & filters.
  128. ------------------------------------------------------------------------*/
  129. int WINAPI WinMain( HINSTANCE hinst,        // instance handle
  130.                     HINSTANCE hinstPrev,    // always NULL
  131.                     LPSTR pszCmd,           // pointer to ANSI command line arguments
  132.                     int nCmdShow)           // initial app window state
  133. {
  134.     CoInitialize(NULL);
  135.  
  136.     ASSERT(!hinstPrev);
  137.     g_hinst = hinst;
  138.     if (!FInitMain(nCmdShow))
  139.     {
  140.         return -1;
  141.     }
  142.  
  143.     // Register for device add/remove notifications.
  144.     DEV_BROADCAST_DEVICEINTERFACE filterData;
  145.     ZeroMemory(&filterData, sizeof(DEV_BROADCAST_DEVICEINTERFACE));   
  146.     filterData.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
  147.     filterData.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
  148.     filterData.dbcc_classguid = AM_KSCATEGORY_CAPTURE;
  149.     g_hDevNotify = RegisterDeviceNotification(g_hwndApp, &filterData, DEVICE_NOTIFY_WINDOW_HANDLE);        
  150.     ASSERT(g_hDevNotify != NULL);
  151.  
  152.     // dvapp setup 
  153.     DV_AppSetup();
  154.  
  155.     return NMsgLoop();
  156. }
  157.  
  158. /*--------------------------------------------------------------------------
  159. Routine:  FInitMain
  160. Purpose:  Initialize the main application window.
  161. Arguments:int initial app window state
  162. Returns:  Return TRUE if successful.
  163. ------------------------------------------------------------------------*/
  164. BOOL FInitMain( int nCmdShow)
  165. {
  166.     WNDCLASSEX      wc;
  167.  
  168.     INITCOMMONCONTROLSEX icc;
  169.     // register common control classes
  170.     icc.dwSize = sizeof(icc);
  171.     icc.dwICC = ICC_BAR_CLASSES;
  172.     InitCommonControlsEx(&icc);
  173.  
  174.     // register the window class
  175.     ZeroMemory(&wc, sizeof(wc));
  176.     wc.cbSize           = sizeof(wc);
  177.     wc.style            = CS_HREDRAW | CS_VREDRAW;
  178.     wc.lpfnWndProc      = MainWndProc;
  179.     wc.cbClsExtra       = 0 ;
  180.     wc.cbWndExtra       = 0 ;
  181.     wc.hInstance        = g_hinst;
  182.     wc.hIcon            = LoadIcon (g_hinst, TEXT("DVICON")) ;
  183.     wc.hCursor          = LoadCursor (NULL, IDC_ARROW) ;
  184.     wc.hbrBackground    = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
  185.     wc.lpszMenuName     = NULL ;
  186.     wc.lpszClassName    = APPNAME ;
  187.     wc.hIconSm          = LoadIcon(g_hinst, TEXT("DVICON"));   
  188.     if (!RegisterClassEx(&wc))
  189.     {
  190.         MessageBox(NULL, TEXT("cannot register the window class"), TEXT("Error"), 0);
  191.         return FALSE;
  192.     }
  193.  
  194.     g_hmenu = LoadMenu(g_hinst, MAKEINTRESOURCE(IDR_MENU));
  195.     // create the main application window
  196.     g_hwndApp = CreateWindowEx(
  197.         0,
  198.         APPNAME,    // window class name
  199.         DV_APPTITLE,    // window caption
  200.         WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX, // window style
  201.         CW_USEDEFAULT,  // initial x position
  202.         CW_USEDEFAULT,  // initial y position
  203.         g_iAppWidth,    // initial x size
  204.         g_iAppHeight,   // initial y size
  205.         NULL,           // parent window handle
  206.         g_hmenu,        // window menu handle
  207.         g_hinst,        // program instance handle
  208.         0) ;            // creation parameters
  209.     
  210.     if (!g_hwndApp)
  211.     {
  212.         MBOX(TEXT("Create main window failed"));
  213.         return FALSE;
  214.     }
  215.  
  216.     // show the window
  217.     ShowWindow(g_hwndApp, nCmdShow);
  218.     UpdateWindow(g_hwndApp);
  219.     SetWindowText(g_hwndApp, TEXT("Initializing..."));
  220.  
  221.     return TRUE;
  222. }
  223.  
  224. /*--------------------------------------------------------------------------
  225. Routine:  NMsgLoop
  226. Purpose:  Execute the program message loop.
  227. Arguments:None
  228. Returns:  Return the wParam field of the final WM_QUIT message.
  229. ------------------------------------------------------------------------*/ 
  230. int NMsgLoop(void)
  231. {
  232.     MSG msg;
  233.     while (GetMessage(&msg, NULL, 0, 0))
  234.     {   
  235.         TranslateMessage(&msg);
  236.         DispatchMessage(&msg);              
  237.     }
  238.  
  239.     return ((int) msg.wParam);
  240. }
  241.  
  242. /*--------------------------------------------------------------------------
  243. Routine:  MainWndProc
  244. Purpose:  Window procedure for the main application window.
  245. Arguments:Usual
  246. Returns:  Usual
  247. ------------------------------------------------------------------------*/ 
  248. LRESULT CALLBACK MainWndProc(
  249.     HWND hwnd,
  250.     UINT msg,
  251.     WPARAM wparam,
  252.     LPARAM lparam)
  253. {
  254.     switch (msg)
  255.     {
  256.         case WM_CREATE:
  257.             if (!DV_InitControls(hwnd, (HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE)))
  258.             {
  259.                 MBOX(TEXT("DV_InitControls failed to create one of the control windows"));
  260.             }
  261.             break;
  262.  
  263.         case WM_SIZE:
  264.         {
  265.             RECT  rcAppWin, rcClient, rcTB;
  266.             //re-size the App window
  267.             int cxBorder = GetSystemMetrics(SM_CXBORDER);
  268.             int cyBorder = GetSystemMetrics(SM_CYBORDER);
  269.             GetWindowRect(g_hwndApp, &rcAppWin);
  270.             GetWindowRect(g_hwndTBar, &rcTB);
  271.             MoveWindow(g_hwndApp, rcAppWin.left, rcAppWin.top, g_iAppWidth, g_iAppHeight, TRUE);
  272.  
  273.             // Tell the toolbar to resize itself to fill the top of the window.
  274.             SendMessage(g_hwndTBar, TB_AUTOSIZE, 0L, 0L);
  275.  
  276.             //handle the status bar height
  277.             GetClientRect(g_hwndApp, &rcClient);
  278.             cxBorder = GetSystemMetrics(SM_CXBORDER);
  279.             cyBorder = GetSystemMetrics(SM_CYBORDER);
  280.             MoveWindow(g_hwndStatus, -cxBorder, rcClient.bottom - (g_statusHeight + cyBorder), 
  281.                        rcClient.right + (2 * cxBorder), (g_statusHeight + (2 * cyBorder)), TRUE);  
  282.  
  283.             DV_StatusParts(rcClient.right);
  284.         
  285.             //re-size the video window
  286.             GetWindowRect(g_hwndTBar, &rcTB);
  287.             if (g_pGraph )
  288.             {
  289.                 if(g_pGraph->m_pVideoWindow)
  290.                 {
  291.                     g_pGraph->m_pVideoWindow->SetWindowPosition(0, rcTB.bottom - rcTB.top, g_iVWWidth, g_iVWHeight);
  292.                 }
  293.             }
  294.             break;          
  295.         }           
  296.  
  297.         case WM_CLOSE:
  298.             return SendMessage(hwnd, WM_DESTROY, 0,0);
  299.  
  300.         case WM_DESTROY:
  301.             // Unregister device notifications
  302.             if (g_hDevNotify != NULL)
  303.             {
  304.                 UnregisterDeviceNotification(g_hDevNotify);
  305.                 g_hDevNotify = NULL;
  306.             }       
  307.             //  Kill the graph
  308.             if(g_pGraph != NULL)
  309.                 delete g_pGraph;
  310.  
  311.             CoUninitialize();
  312.  
  313.             PostQuitMessage(0);
  314.             break;
  315.  
  316.         case WM_DEVICECHANGE:
  317.         {
  318.             // We are interested in only device arrival events
  319.             if (DBT_DEVICEARRIVAL != wparam)
  320.                 break;
  321.             PDEV_BROADCAST_HDR pdbh = (PDEV_BROADCAST_HDR) lparam;
  322.             if (pdbh->dbch_devicetype != DBT_DEVTYP_DEVICEINTERFACE)
  323.                 break;
  324.  
  325.             // Check for capture devices.
  326.             PDEV_BROADCAST_DEVICEINTERFACE pdbi = (PDEV_BROADCAST_DEVICEINTERFACE) lparam;
  327.             if (pdbi->dbcc_classguid != AM_KSCATEGORY_CAPTURE)
  328.                 break;
  329.  
  330.             // Check for device arrival.
  331.             if (g_bDeviceFound == FALSE)
  332.             {
  333.                 MessageBox(g_hwndApp, TEXT("There is a new capture device on this system..."), APPNAME, MB_OK);
  334.                 DV_AppSetup();
  335.             }
  336.             break;
  337.         }
  338.  
  339.        case WM_FGNOTIFY :            //Filter Graph Events Notify Message handler
  340.        {
  341.            if(g_pGraph->m_pMediaEvent == NULL)
  342.                break;
  343.  
  344.             long event;
  345.             LONG_PTR l1, l2;
  346.             // Get the corresponding filtergraph directshow media event to handle
  347.             while (SUCCEEDED(g_pGraph->m_pMediaEvent->GetEvent(&event, &l1, &l2, 0L)))
  348.             {
  349.                 switch (event)
  350.                 {
  351.                 case EC_USERABORT :
  352.                 case EC_COMPLETE :
  353.                     // filtergraph is done, time to stop the filtergraph or transport state
  354.                     SendMessage(g_hwndApp, WM_COMMAND, IDM_STOP, 0);  
  355.                     break;
  356.             
  357.                 case EC_ERRORABORT :
  358.                     //something bad happened during capture
  359.                     MBOX(TEXT("Error during preview, capture or transmit"));
  360.                     break;
  361.  
  362.                 case EC_DEVICE_LOST :   // Check if we have lost a capture filter being used.
  363.                     if (l2 == 0)        //0 indicates device removed;1 indicates removed device added again
  364.                     {
  365.                         IBaseFilter *pf;
  366.                         IUnknown *punk = (IUnknown *) l1;
  367.                         HRESULT hr = punk->QueryInterface(IID_IBaseFilter, (void **) &pf);
  368.                         if(FAILED(hr))
  369.                             break;
  370.                     
  371.                         if (::IsEqualObject(g_pGraph->m_pDeviceFilter, pf))
  372.                         {
  373.                             MBOX(TEXT("DV Camcorder Device in use was removed"));
  374.  
  375.                             // handle the timers accordingly
  376.                             if (g_bUseAtnTimer)
  377.                                 KillTimer(hwnd, DV_TIMER_ATN);
  378.                             KillTimer(hwnd, DV_TIMER_CAPLIMIT);
  379.                             KillTimer(hwnd, DV_TIMER_FRAMES);
  380.                             g_bDeviceFound = FALSE;
  381.  
  382.                             // should call nuke filters....????
  383.                             if(g_pGraph != NULL)
  384.                                 delete g_pGraph; //  pf is released
  385.                             DV_AppSetup();
  386.                         }
  387.                         else
  388.                             pf->Release();               
  389.                     }
  390.                     break;
  391.                 default:
  392.                     break;
  393.  
  394.                 }// end of switch
  395.                 if(g_pGraph->m_pMediaEvent == NULL)
  396.                break;
  397.             } // end of while
  398.             break;
  399.         }
  400.  
  401.         case WM_COMMAND:
  402.         switch (LOWORD(wparam))
  403.         {
  404.             // The File Menu 
  405.             /*  
  406.                 The globals for input file and output file are TCHAR.  When compiled ANSI,
  407.                 GetOpenFileName (obviously) return ANSI buffers.  DShow functions use Unicode
  408.                 names exclusively, so these are converted to Unicode within the functions 
  409.                 that need to use these variables (DV_Make...To... functions).
  410.             */
  411.             case IDM_SETINPUT :    //fall through
  412.             case IDM_SETOUTPUT :
  413.             case IDM_OPTIONS_SAVEGRAPH :
  414.             {
  415.                 OPENFILENAME ofn = {0};
  416.                 OSVERSIONINFO osi = {0};
  417.                 //need to adjust the ofn struct size if we are running on win98 vs. nt5
  418.                 osi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  419.                 GetVersionEx(&osi);
  420.                 if (osi.dwMajorVersion >=5 && osi.dwPlatformId == VER_PLATFORM_WIN32_NT)
  421.                 {
  422.                     ofn.lStructSize = sizeof (OPENFILENAME);
  423.                 } 
  424.                 else
  425.                 {
  426.                     ofn.lStructSize = sizeof(OPENFILENAME);
  427.                 }   
  428.             
  429.                 ofn.hwndOwner = g_hwndApp;
  430.                 ofn.nMaxFile = _MAX_PATH;
  431.                 if (IDM_OPTIONS_SAVEGRAPH == LOWORD (wparam))
  432.                 {
  433.                     ofn.lpstrFilter = TEXT("Filter Graph\0*.grf\0\0");
  434.                     ofn.lpstrTitle = TEXT("Set FilterGraph File Name");
  435.                     ofn.lpstrFile = g_FilterGraphFileName;
  436.                 } 
  437.                 else if (IDM_SETOUTPUT == LOWORD (wparam))
  438.                 {
  439.                     ofn.lpstrFilter = TEXT("Microsoft AVI\0*.avi\0\0");
  440.                     ofn.lpstrTitle = TEXT("Set output File Name");
  441.                     ofn.lpstrFile = g_OutputFileName;
  442.                 } 
  443.                 else
  444.                 {
  445.                     ofn.lpstrFilter = TEXT("Microsoft AVI\0*.avi\0\0");
  446.                     ofn.lpstrTitle = TEXT("Set input File Name");
  447.                     ofn.lpstrFile = g_InputFileName;
  448.                 } 
  449.  
  450.                 if (GetOpenFileName(&ofn))
  451.                 {
  452.                     if (IDM_OPTIONS_SAVEGRAPH == LOWORD (wparam))
  453.                     {
  454.                         lstrcpy(g_FilterGraphFileName, ofn.lpstrFile);
  455.                         // Save the current built filter graph to a *.grf file
  456.                         if(g_pGraph != NULL)
  457.                             g_pGraph->SaveGraphToFile(g_FilterGraphFileName);
  458.                         
  459.                     } 
  460.                     else if (IDM_SETOUTPUT == LOWORD (wparam))
  461.                     {
  462.                         lstrcpy(g_OutputFileName, ofn.lpstrFile);
  463.                     } 
  464.                     else
  465.                     {
  466.                         lstrcpy(g_InputFileName, ofn.lpstrFile);
  467.                     } 
  468.                 }
  469.                 break;    
  470.             } 
  471.             case IDM_ABOUT:
  472.                 DialogBox((HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE), MAKEINTRESOURCE(IDD_ABOUT), hwnd, (DLGPROC)DV_AboutDlgProc);
  473.                 break;
  474.  
  475.             // Toolbar Button Commands
  476.             // Transport State & Graph State Control
  477.             case IDM_PLAY :
  478.             case IDM_RECORD :
  479.             case IDM_STOP : 
  480.             case IDM_PAUSE :
  481.             case IDM_FF :
  482.             case IDM_REW :
  483.             case IDM_PLAY_FAST_FF :
  484.             case IDM_PLAY_FAST_REV :        
  485.             case IDM_STEP_FWD :
  486.             case IDM_STEP_REV :
  487.             case IDM_SEEKTIMECODE :
  488.                 DV_TransportCommand_WndProc(hwnd, msg, wparam, lparam);
  489.                 break;
  490.  
  491.             // The Options Menu
  492.             case IDM_DECODESIZE :
  493.                 g_pGraph->StopGraph();
  494.                 g_pGraph->GetVideoWindowDimensions(&g_iVWWidth, &g_iVWHeight, TRUE, g_hwndApp);
  495.                 g_iAppWidth = g_iVWWidth + WIDTH_EDGE;
  496.                 g_iAppHeight = g_iVWHeight + HEIGHT_EDGE;
  497.                 //resize the window
  498.                 PostMessage(g_hwndApp, WM_SIZE, SIZE_RESTORED, MAKELONG(g_iAppWidth, g_iAppHeight));
  499.                 break;
  500.  
  501.             case IDM_CHECKTAPE :
  502.                 DV_UpdateTapeInfo();
  503.                 break;
  504.  
  505.             case IDM_REFRESHMODE :
  506.                 DV_RefreshMode();
  507.                 break;
  508.  
  509.             case IDM_FRAMERATE :
  510.                 if( g_bHalfFrameRate )
  511.                 {
  512.                     g_bHalfFrameRate = FALSE;
  513.                     CheckMenuItem(g_hmenu, IDM_FRAMERATE, MF_UNCHECKED);
  514.                 }
  515.                 else
  516.                 {
  517.                     g_bHalfFrameRate = TRUE;
  518.                     CheckMenuItem(g_hmenu, IDM_FRAMERATE, MF_CHECKED);                   
  519.                 }
  520.                 g_pGraph->ChangeFrameRate(g_bHalfFrameRate);
  521.                 break;
  522.  
  523.             case IDM_CAPSIZE:
  524.               DialogBox((HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE), MAKEINTRESOURCE(IDD_DIALOG_CAPSIZE), hwnd, (DLGPROC)DV_CapSizeDlgProc);
  525.               break;
  526.  
  527.             case IDM_EXIT:
  528.                 return SendMessage(hwnd, WM_CLOSE, 0, 0);
  529.                 
  530.             // Graph Mode Menu
  531.             // Change the Current Graph Mode
  532.             case IDM_PREVIEW :
  533.             case IDM_FILETODV :
  534.             case IDM_FILETODV_NOPRE :
  535.             case IDM_DVTOFILE :
  536.             case IDM_DVTOFILE_NOPRE :
  537.             case IDM_FILETODV_TYPE2 :
  538.             case IDM_FILETODV_NOPRE_TYPE2 :
  539.             case IDM_DVTOFILE_TYPE2 :
  540.             case IDM_DVTOFILE_NOPRE_TYPE2 :            
  541.                 DV_GraphModeCommand_WndProc (hwnd, msg, wparam, lparam);
  542.                 
  543.                 break;
  544.         }
  545.         break;
  546.  
  547.         default:
  548.             return DefWindowProc(hwnd, msg, wparam, lparam);
  549.     }
  550.  
  551.     return 0;
  552. }
  553.  
  554. /*-------------------------------------------------------------------------
  555. Routine:        DV_InitControls
  556. Purpose:        Initializer for app window controls (toolbars, edit controls, etc.)
  557. Arguments:    window handle and hinstance
  558. Returns:        FALSE if creation of any of the controls fails.
  559. Notes:          
  560. ------------------------------------------------------------------------*/
  561. BOOL DV_InitControls(HWND hwnd, HINSTANCE hInst)
  562. {
  563.     HWND hwndEdit1 = NULL;
  564.     HWND hwndEdit2 = NULL;
  565.     HWND hwndEdit3 = NULL;
  566.     HWND hwndEdit4 = NULL;
  567.     HWND hwndTCCheck = NULL;
  568.  
  569.     RECT rect = {0};
  570.  
  571.     // create status bar windows
  572.     g_hwndStatus = CreateWindowEx( 0,
  573.                                    STATUSCLASSNAME,
  574.                                    TEXT(""),
  575.                                    WS_CHILD | WS_BORDER | WS_VISIBLE | WS_CLIPSIBLINGS,
  576.                                    -100, -100,
  577.                                    10, 10,
  578.                                    hwnd,
  579.                                    HMENU(IDB_STATUS),
  580.                                    g_hinst,
  581.                                    NULL);
  582.  
  583.     DV_StatusParts(g_iAppWidth);
  584.     g_statusHeight = rect.bottom;
  585.  
  586.     // create toolbar window
  587.     g_hwndTBar = CreateToolbarEx(hwnd, 
  588.                                    WS_CHILD | WS_VISIBLE | WS_BORDER | TBSTYLE_TOOLTIPS, 
  589.                                    ID_TOOLBAR, 
  590.                                    10, 
  591.                                    g_hinst, 
  592.                                    IDB_TOOLBAR, 
  593.                                    g_rgTbButtons, 
  594.                                    sizeof(g_rgTbButtons) / sizeof(TBBUTTON), 
  595.                                    16,16,16,16, 
  596.                                    sizeof(TBBUTTON)); 
  597.  
  598.     // create timecode text boxes on the toolbar        
  599.     rect.right = 350;
  600.     hwndEdit1 = CreateWindow(TEXT("edit"), TEXT("00"), WS_CHILD | WS_BORDER | WS_VISIBLE | WS_TABSTOP | ES_NUMBER, 
  601.                     rect.right + 6, 4, 22, 18, g_hwndTBar, (HMENU)IDC_EDIT_HOUR, (HINSTANCE) hInst, NULL);
  602.     
  603.     hwndEdit2 = CreateWindow(TEXT("edit"), TEXT("00"), WS_CHILD | WS_BORDER | WS_VISIBLE | WS_TABSTOP | ES_NUMBER,  
  604.                     rect.right + 30, 4, 22, 18, g_hwndTBar, (HMENU)IDC_EDIT_MINUTE, (HINSTANCE) hInst, NULL);
  605.     
  606.     hwndEdit3 = CreateWindow(TEXT("edit"), TEXT("00"), WS_CHILD | WS_BORDER | WS_VISIBLE | WS_TABSTOP | ES_NUMBER, 
  607.                     rect.right + 54, 4, 22, 18, g_hwndTBar, (HMENU)IDC_EDIT_SECOND, (HINSTANCE) hInst, NULL);
  608.  
  609.     hwndEdit4 = CreateWindow(TEXT("edit"), TEXT("00"), WS_CHILD | WS_BORDER | WS_VISIBLE | WS_TABSTOP | ES_NUMBER, 
  610.                     rect.right + 78, 4, 22, 18, g_hwndTBar, (HMENU)IDC_EDIT_FRAME, (HINSTANCE) hInst, NULL);
  611.  
  612.     hwndTCCheck = CreateWindow(TEXT("button"), TEXT("Display Timecodes"), WS_CHILD | BS_AUTOCHECKBOX | WS_VISIBLE | WS_TABSTOP, 
  613.                     rect.right + 106, 5, 190, 18, g_hwndTBar, (HMENU)IDC_TCCHECKBOX, (HINSTANCE) hInst, NULL); 
  614.     Button_SetCheck (hwndTCCheck, BST_CHECKED) ;                    
  615.  
  616.     return (!( !hwndEdit1) || (!hwndEdit2) || (!hwndEdit3) || (!hwndEdit4) || (!hwndTCCheck) || (!g_hwndStatus));
  617.  
  618. /*-------------------------------------------------------------------------
  619. Routine:        DV_AppSetup
  620. Purpose:        look for a DV device, initialize it, get its subunit mode, 
  621.                     Create the filtergraph and instantiate the filters
  622. Arguments:    None
  623. Returns:        None
  624. Notes:          
  625. ------------------------------------------------------------------------*/
  626. HRESULT DV_AppSetup(void)
  627. {   
  628.     HRESULT hr =S_OK;
  629.     g_pGraph = new CDVGraph();
  630.     if ( !g_pGraph ){
  631.        hr = E_OUTOFMEMORY;
  632.        return hr;
  633.     }
  634.     
  635.     //look for a DV device and initialize it, or show an error if one does not exist 
  636.     hr = g_pGraph->BuildBasicGraph();
  637.     if (S_OK != hr) 
  638.     {
  639.         g_bDeviceFound = FALSE;
  640.         int iOption = MessageBox(g_hwndApp, TEXT("There are no DV camcorder devices on this system.\n\n")
  641.                                  TEXT("Do you want to exit the app?"), APPNAME, MB_YESNO);
  642.         if(iOption == IDYES) 
  643.             SendMessage(g_hwndApp, WM_DESTROY, 0,0);
  644.         else
  645.         {
  646.             ShowWindow(g_hwndTBar, SW_HIDE);
  647.  
  648.             EnableMenuItem(g_hmenu, IDM_REFRESHMODE, MF_GRAYED);
  649.             EnableMenuItem(g_hmenu, IDM_CHECKTAPE, MF_GRAYED);
  650.             EnableMenuItem(g_hmenu, IDM_DECODESIZE, MF_GRAYED);
  651.  
  652.             EnableMenuItem(g_hmenu, IDM_PREVIEW, MF_GRAYED);
  653.             EnableMenuItem(g_hmenu, IDM_DVTOFILE, MF_GRAYED);
  654.             EnableMenuItem(g_hmenu, IDM_DVTOFILE_NOPRE, MF_GRAYED);
  655.             EnableMenuItem(g_hmenu, IDM_FILETODV, MF_GRAYED);
  656.             EnableMenuItem(g_hmenu, IDM_FILETODV_NOPRE, MF_GRAYED);
  657.             EnableMenuItem(g_hmenu, IDM_DVTOFILE_TYPE2, MF_GRAYED);
  658.             EnableMenuItem(g_hmenu, IDM_DVTOFILE_NOPRE_TYPE2, MF_GRAYED);
  659.             EnableMenuItem(g_hmenu, IDM_FILETODV_TYPE2, MF_GRAYED);
  660.             EnableMenuItem(g_hmenu, IDM_FILETODV_NOPRE_TYPE2, MF_GRAYED);
  661.         }
  662.     }
  663.     else
  664.     {
  665.         g_bDeviceFound = TRUE;
  666.         ShowWindow(g_hwndTBar, SW_SHOWNORMAL);
  667.  
  668.         EnableMenuItem(g_hmenu, IDM_REFRESHMODE, MF_ENABLED);
  669.         EnableMenuItem(g_hmenu, IDM_CHECKTAPE, MF_ENABLED);
  670.         EnableMenuItem(g_hmenu, IDM_DECODESIZE, MF_ENABLED);
  671.  
  672.         EnableMenuItem(g_hmenu, IDM_PREVIEW, MF_ENABLED);
  673.         EnableMenuItem(g_hmenu, IDM_DVTOFILE, MF_ENABLED);
  674.         EnableMenuItem(g_hmenu, IDM_DVTOFILE_NOPRE, MF_ENABLED);
  675.         EnableMenuItem(g_hmenu, IDM_FILETODV, MF_ENABLED);
  676.         EnableMenuItem(g_hmenu, IDM_FILETODV_NOPRE, MF_ENABLED);
  677.         EnableMenuItem(g_hmenu, IDM_DVTOFILE_TYPE2, MF_ENABLED);
  678.         EnableMenuItem(g_hmenu, IDM_DVTOFILE_NOPRE_TYPE2, MF_ENABLED);
  679.         EnableMenuItem(g_hmenu, IDM_FILETODV_TYPE2, MF_ENABLED);
  680.         EnableMenuItem(g_hmenu, IDM_FILETODV_NOPRE_TYPE2, MF_ENABLED);
  681.  
  682.  
  683.         //determine if we are in camera mode or vcr mode and disable unavailable menu items
  684.         DV_RefreshMode();
  685.  
  686.         DV_StatusText(g_pGraph->m_DeviceName, 0);
  687.  
  688.  
  689.         // make preview graph
  690.         hr= g_pGraph->MakePreviewGraph( );
  691.         if(FAILED(hr))
  692.         {
  693.             MBOX(TEXT("MakePreviewGraph() failed"));
  694.             return hr;
  695.         }  
  696.  
  697.         //get and set the display window size
  698.         g_pGraph->GetVideoWindowDimensions(&g_iVWWidth, &g_iVWHeight, FALSE, NULL);
  699.         g_iAppWidth = g_iVWWidth + WIDTH_EDGE;
  700.         g_iAppHeight = g_iVWHeight + HEIGHT_EDGE;
  701.         PostMessage(g_hwndApp, WM_SIZE, SIZE_RESTORED, MAKELONG(g_iAppWidth, g_iAppHeight));
  702.  
  703.         // register a window to process event notifications.     
  704.         hr = g_pGraph->m_pMediaEvent->SetNotifyWindow((LONG_PTR) g_hwndApp, WM_FGNOTIFY, 0);
  705.         if(FAILED(hr))
  706.         {
  707.             MBOX(TEXT("g_pGraph->m_pMediaEvent->SetNotifyWindow() failed"));
  708.             return hr;
  709.         }
  710.      
  711.         // update globals, log, toolbar, menu items for preview mode
  712.         g_iGraphType = GRAPH_PREVIEW;
  713.         Mark_GraphMode_Menu( g_hwndApp, IDM_PREVIEW );   
  714.         Mark_ToolBar_Button( FALSE, TRUE );    
  715.         SetPreviewWindow();
  716.         
  717.         // ready for user
  718.         SetWindowText(g_hwndApp, DV_APPTITLE);     
  719.     }
  720.  
  721.     return hr;
  722. }
  723.  
  724. /*-------------------------------------------------------------------------
  725. Routine:        DV_GraphModeCommand_WndProc
  726. Purpose:        Message Handler for Graph Mode menu items
  727. Arguments:    Usual message processing parameters
  728. Returns:        Usual
  729. Notes:          Builds the various kinds of Graph types preview/capture/transmit
  730. ------------------------------------------------------------------------*/
  731. void CALLBACK DV_GraphModeCommand_WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
  732.     HRESULT hr;
  733.     GRAPH_TYPE graphType;
  734.     GetSelectedGraphMode( wParam, &graphType );
  735.  
  736.     // dont rebuild if the required graph already exists
  737.     if( graphType == g_iGraphType )
  738.         return;
  739.  
  740.     //stop the graph - this should never fail before rebuilding
  741.     if(FAILED( g_pGraph->m_pMediaControl->Stop()))
  742.     {
  743.         return;
  744.     }
  745.  
  746.  
  747.     //let's look at the former graph
  748.     //Disconnect everything
  749.     if (GRAPH_FILE_TO_DV == g_iGraphType || GRAPH_FILE_TO_DV_NOPRE == g_iGraphType ||
  750.         GRAPH_FILE_TO_DV_TYPE2 == g_iGraphType || GRAPH_FILE_TO_DV_NOPRE_TYPE2 == g_iGraphType)
  751.     {
  752.         //DisconnectAll removes only the downstream filters - we need to remove the file filter by hand.
  753.          g_pGraph->NukeFilters( g_pGraph->m_pInputFileFilter, TRUE);
  754.         if (g_pGraph->m_pInputFileFilter )
  755.         {
  756.             g_pGraph->m_pGraph->RemoveFilter( g_pGraph->m_pInputFileFilter );
  757.             SAFE_RELEASE( g_pGraph->m_pInputFileFilter );        
  758.         }
  759.     } 
  760.     else
  761.     {
  762.         //DisconnectAll removes only the downstream filters         
  763.         hr = g_pGraph->NukeFilters( g_pGraph->m_pDeviceFilter, TRUE);
  764.         if(FAILED(hr))
  765.         {
  766.             MBOX(TEXT("nukefilters() failed"));
  767.         }
  768.     }
  769.     g_iGraphType = graphType;
  770.  
  771.     switch (LOWORD (wParam))
  772.     {   
  773.     case IDM_PREVIEW :
  774.         if(SUCCEEDED(g_pGraph->MakePreviewGraph( )))
  775.         {
  776.             // update globals, log, toolbar, menu items
  777.             SetPreviewWindow();
  778.             Mark_GraphMode_Menu( hwnd, IDM_PREVIEW );   
  779.             Mark_ToolBar_Button( FALSE, FALSE );    
  780.         }
  781.         else
  782.             MBOX(TEXT("MakePreviewGraph() failed"));
  783.  
  784.         break;
  785.  
  786.     // Type 1 file (transmit & playback)    
  787.     case IDM_FILETODV :
  788.         if(SUCCEEDED(g_pGraph->MakeFileToDvGraph_Type1( g_InputFileName )))
  789.         {
  790.             // update globals, log, toolbar, menu items
  791.             SetPreviewWindow();
  792.             Mark_GraphMode_Menu( hwnd,IDM_FILETODV );   
  793.             Mark_ToolBar_Button( TRUE, FALSE ); 
  794.         } 
  795.         else
  796.             MBOX(TEXT("MakeFileToDvGraph_Type1() failed"));
  797.     
  798.         break;
  799.  
  800.     // Type 1 file (transmit)   
  801.     case IDM_FILETODV_NOPRE :
  802.         if(SUCCEEDED(g_pGraph->MakeFileToDvGraph_NoPre_Type1( g_InputFileName )))
  803.         {
  804.             // update globals, log, toolbar, menu items
  805.             Mark_GraphMode_Menu( hwnd,IDM_FILETODV_NOPRE );   
  806.             Mark_ToolBar_Button( TRUE, FALSE ); 
  807.         }
  808.         else
  809.             MBOX(TEXT("MakeFileToDvGraph_NoPre_Type1() failed")); 
  810.         break;
  811.         
  812.     // Type 1 file (capture & preview)  
  813.     case IDM_DVTOFILE :
  814.         if(SUCCEEDED(g_pGraph->MakeDvToFileGraph_Type1( g_OutputFileName )))
  815.         {
  816.             // update globals, log, toolbar, menu items
  817.             SetPreviewWindow();
  818.             Mark_GraphMode_Menu( hwnd,IDM_DVTOFILE );   
  819.             Mark_ToolBar_Button( TRUE, TRUE );  
  820.         }
  821.         else
  822.             MBOX(TEXT("MakeDvToFileGraph_Type1() failed"));
  823.             
  824.         break;
  825.  
  826.     // Type 1 file (capture)    
  827.     case IDM_DVTOFILE_NOPRE :
  828.         if(SUCCEEDED(g_pGraph->MakeDvToFileGraph_NoPre_Type1( g_OutputFileName )))
  829.         {
  830.             // update globals, log, toolbar, menu items
  831.             Mark_GraphMode_Menu( hwnd,IDM_DVTOFILE_NOPRE );   
  832.             Mark_ToolBar_Button( TRUE, TRUE );  
  833.         }
  834.         else
  835.             MBOX(TEXT("MakeDvToFileGraph_NoPre_Type1() failed"));
  836.         
  837.         break;
  838.  
  839.     // Type 2 File (transmit & playback)
  840.     case IDM_FILETODV_TYPE2 :
  841.         if(SUCCEEDED(g_pGraph->MakeFileToDvGraph_Type2( g_InputFileName )))
  842.         {
  843.             // update globals, log, toolbar, menu items
  844.             SetPreviewWindow();
  845.             Mark_GraphMode_Menu( hwnd,IDM_FILETODV_TYPE2 );   
  846.             Mark_ToolBar_Button( TRUE, FALSE ); 
  847.         }
  848.         else
  849.             MBOX(TEXT("MakeFileToDvGraph_Type2() failed"));
  850.                 
  851.         break;
  852.  
  853.     // Type 2 File (transmit)
  854.     case IDM_FILETODV_NOPRE_TYPE2 :
  855.         if(SUCCEEDED(g_pGraph->MakeFileToDvGraph_NoPre_Type2( g_InputFileName )))
  856.         {
  857.             // update globals, log, toolbar, menu items
  858.             Mark_GraphMode_Menu( hwnd,IDM_FILETODV_NOPRE_TYPE2 );   
  859.             Mark_ToolBar_Button( TRUE, FALSE ); 
  860.         }
  861.         else
  862.             MBOX(TEXT("MakeFileToDvGraph_NoPre_Type2() failed"));
  863.                 
  864.         break;
  865.         
  866.     // Type 2 File (capture & preview)
  867.     case IDM_DVTOFILE_TYPE2 :
  868.         if(SUCCEEDED(g_pGraph->MakeDvToFileGraph_Type2( g_OutputFileName )))
  869.         {
  870.             // update globals, log, toolbar, menu items
  871.             SetPreviewWindow();
  872.             Mark_GraphMode_Menu( hwnd,IDM_DVTOFILE_TYPE2 );   
  873.             Mark_ToolBar_Button( TRUE, TRUE );  
  874.         } 
  875.         else
  876.             MBOX(TEXT("MakeDvToFileGraph_Type2() failed"));
  877.     
  878.         break;
  879.  
  880.     // Type 2 File (capture)
  881.     case IDM_DVTOFILE_NOPRE_TYPE2 :
  882.         if(SUCCEEDED(g_pGraph->MakeDvToFileGraph_NoPre_Type2( g_OutputFileName )))
  883.         {
  884.             // update globals, log, toolbar, menu items
  885.             Mark_GraphMode_Menu( hwnd,IDM_DVTOFILE_NOPRE_TYPE2 );   
  886.             Mark_ToolBar_Button( TRUE, TRUE );  
  887.         } 
  888.         else
  889.             MBOX(TEXT("MakeDvToFileGraph_NoPre_Type2() failed"));
  890.         
  891.         break;
  892.     } // switch (LOWORD(wParam))
  893. }
  894.  
  895. /*-------------------------------------------------------------------------
  896. Routine:        DV_TransportCommand_WndProc 
  897. Purpose:        Message Handler to control transport state of the device & the filtergraph state
  898. Arguments:    Usual message processing parameters
  899. Returns:        Usual
  900. Notes:          Handles for the Toolbar button controls
  901. ------------------------------------------------------------------------*/
  902. void CALLBACK DV_TransportCommand_WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
  903. {
  904.     switch (iMsg)
  905.     {
  906.     case WM_COMMAND :
  907.         switch (LOWORD (wParam))
  908.         {
  909.         /*
  910.             The VCR Tool bar commands need to behave differently depending on the 
  911.             current graph.  
  912.  
  913.             In Preview (default) mode, the VCR commands should simply
  914.             control the VCR functions on the vcr device.
  915.  
  916.             In DV To File mode, or File To DV mode the commands should start and stop the graph, 
  917.             as  well as control the vcr mode (although we will disable some buttons to avoid confusion)
  918.         */
  919.         case IDM_PLAY :
  920.         {
  921.             //check if the current graph is a transmit graph
  922.             if (GRAPH_FILE_TO_DV == g_iGraphType || GRAPH_FILE_TO_DV_NOPRE == g_iGraphType || 
  923.                 GRAPH_FILE_TO_DV_TYPE2 == g_iGraphType || GRAPH_FILE_TO_DV_NOPRE_TYPE2 == g_iGraphType)
  924.             {
  925.                 // update the toolbar accordingly
  926.                 SendMessage(g_hwndTBar, TB_SETSTATE, IDM_PLAY, MAKELONG(TBSTATE_INDETERMINATE, 0L));
  927.                 // update the status bar with the dropped frames information
  928.                 g_CapStartTime = GetTickCount();
  929.                 SetTimer(hwnd, DV_TIMER_FRAMES,  DV_TIMERFREQ, (TIMERPROC) DV_DroppedFrameProc);
  930.                 // run the filter graph & wait for dshow events
  931.                 g_pGraph->StartGraph();
  932.  
  933.             } 
  934.             else //capture and preview
  935.             {
  936.                 // play the tape for the capture or preview graph
  937.                 DV_PutVcrMode(ED_MODE_PLAY);
  938.  
  939.                 if(GRAPH_PREVIEW == g_iGraphType)
  940.                     g_pGraph->StartGraph();
  941.  
  942.                 //do we want to display timecodes?
  943.                 if (IsDlgButtonChecked(g_hwndTBar, IDC_TCCHECKBOX))
  944.                {
  945.                     SetTimer(hwnd, DV_TIMER_ATN,  DV_TIMERFREQ, (TIMERPROC) DV_TimecodeTimerProc);
  946.                     g_bUseAtnTimer = TRUE;
  947.                 } 
  948.             } 
  949.             break;
  950.         }
  951.  
  952.         /*
  953.             The record button starts the *entire* graph, so preview (if selected), won't
  954.             start until the recording starts.  
  955.         */
  956.         case IDM_RECORD :
  957.             // update the toolbar accordingly
  958.             SendMessage(g_hwndTBar, TB_SETSTATE, IDM_STEP_FWD, MAKELONG(TBSTATE_INDETERMINATE, 0L));
  959.             SendMessage(g_hwndTBar, TB_SETSTATE, IDM_STEP_REV, MAKELONG(TBSTATE_INDETERMINATE, 0L));
  960.  
  961.             // check to see if it is a capture graph
  962.             if (GRAPH_DV_TO_FILE == g_iGraphType || GRAPH_DV_TO_FILE_NOPRE == g_iGraphType ||
  963.                 GRAPH_DV_TO_FILE_TYPE2 == g_iGraphType || GRAPH_DV_TO_FILE_NOPRE_TYPE2 == g_iGraphType)
  964.             {
  965.                 //do something here to record to an avi file on the disk - or to start recording on the vcr.
  966.                 switch (g_dwCaptureLimit)
  967.                 {
  968.                     case DV_CAPLIMIT_NONE :
  969.                         break;
  970.                     case DV_CAPLIMIT_TIME :
  971.                         SetTimer(hwnd, DV_TIMER_CAPLIMIT, g_dwTimeLimit * 1000, (TIMERPROC) DV_StopRecProc);
  972.                         break;
  973.                     case DV_CAPLIMIT_SIZE :
  974.                         //rather than monitor disk usage, we'll just do the math and set a timer
  975.                         SetTimer(hwnd, DV_TIMER_CAPLIMIT, ((g_dwDiskSpace * 100000) / DV_BYTESPERMSEC), (TIMERPROC) DV_StopRecProc);
  976.                         break;
  977.                     default :
  978.                         //MBOX(TEXT("Bad value for g_dwCaptureLimit (%d)"), g_dwCaptureLimit);
  979.                         break;
  980.                 }
  981.                 //update the status bar with the dropped frames information
  982.                 g_CapStartTime = GetTickCount();
  983.                 SetTimer(hwnd, DV_TIMER_FRAMES,  DV_TIMERFREQ, (TIMERPROC) DV_DroppedFrameProc);
  984.                 //run the graph - assume that the camera is already playing if in Vcr mode
  985.                 g_pGraph->StartGraph();             
  986.             } 
  987.             else if (GRAPH_FILE_TO_DV == g_iGraphType || GRAPH_FILE_TO_DV_NOPRE == g_iGraphType ||
  988.                      GRAPH_FILE_TO_DV_TYPE2 == g_iGraphType || GRAPH_FILE_TO_DV_NOPRE_TYPE2 == g_iGraphType)
  989.             {
  990.                 // if transmit graph then record on tape of the device
  991.                 DV_PutVcrMode(ED_MODE_RECORD);
  992.             } 
  993.             else
  994.             {
  995.                 //we shouldn't get here
  996.                 MBOX( TEXT("Undefined graph mode (maybe GRAPH_PREVIEW) in IDM_RECORD message"));
  997.             } 
  998.             break;
  999.  
  1000.         case IDM_STOP :   
  1001.             // handle the timers accordingly
  1002.             if (g_bUseAtnTimer)
  1003.                 KillTimer(hwnd, DV_TIMER_ATN);
  1004.             //if we're here, these timers were set
  1005.             KillTimer(hwnd, DV_TIMER_CAPLIMIT);
  1006.             KillTimer(hwnd, DV_TIMER_FRAMES);
  1007.  
  1008.             g_pGraph->StopGraph();
  1009.  
  1010.             // Stop the transport on the device
  1011.             DV_PutVcrMode(ED_MODE_STOP);
  1012.             // update the toolbar 
  1013.             SendMessage(g_hwndTBar, TB_SETSTATE, IDM_PLAY, MAKELONG(TBSTATE_ENABLED, 0L));
  1014.             SendMessage(g_hwndTBar, TB_SETSTATE, IDM_STEP_FWD, MAKELONG(TBSTATE_INDETERMINATE, 0L));
  1015.             SendMessage(g_hwndTBar, TB_SETSTATE, IDM_STEP_REV, MAKELONG(TBSTATE_INDETERMINATE, 0L));
  1016.             break;
  1017.  
  1018.         case IDM_PAUSE :
  1019.             if (GRAPH_FILE_TO_DV == g_iGraphType || GRAPH_FILE_TO_DV_NOPRE == g_iGraphType ||
  1020.                 GRAPH_FILE_TO_DV_TYPE2 == g_iGraphType || GRAPH_FILE_TO_DV_NOPRE_TYPE2 == g_iGraphType)
  1021.             {   // transmit graph
  1022.                 g_pGraph->PauseGraph();
  1023.             } 
  1024.             else
  1025.             {   // capture or preview graph
  1026.                 DV_PutVcrMode(ED_MODE_FREEZE);
  1027.                 SendMessage(g_hwndTBar, TB_SETSTATE, IDM_STEP_FWD, MAKELONG(TBSTATE_ENABLED, 0L));
  1028.                 SendMessage(g_hwndTBar, TB_SETSTATE, IDM_STEP_REV, MAKELONG(TBSTATE_ENABLED, 0L));
  1029.             } 
  1030.             //SendMessage(g_hwndTBar, TB_SETSTATE, IDM_PLAY, MAKELONG(TBSTATE_ENABLED, 0L));
  1031.             break;    
  1032.  
  1033.         case IDM_FF :
  1034.             // all graphs just forward the tape & update the toolbar
  1035.             DV_PutVcrMode(ED_MODE_FF);
  1036.             SendMessage(g_hwndTBar, TB_SETSTATE, IDM_STEP_FWD, MAKELONG(TBSTATE_INDETERMINATE, 0L));
  1037.             SendMessage(g_hwndTBar, TB_SETSTATE, IDM_STEP_REV, MAKELONG(TBSTATE_INDETERMINATE, 0L));
  1038.             break;
  1039.  
  1040.         case IDM_REW :
  1041.             // all graphs just rewind the tape & update the toolbar
  1042.             DV_PutVcrMode(ED_MODE_REW);
  1043.             SendMessage(g_hwndTBar, TB_SETSTATE, IDM_STEP_FWD, MAKELONG(TBSTATE_INDETERMINATE, 0L));
  1044.             SendMessage(g_hwndTBar, TB_SETSTATE, IDM_STEP_REV, MAKELONG(TBSTATE_INDETERMINATE, 0L));
  1045.             break;
  1046.  
  1047.         case IDM_PLAY_FAST_FF :
  1048.             // all graphs just forward the tape & update the toolbar
  1049.             DV_PutVcrMode(ED_MODE_PLAY_FASTEST_FWD);
  1050.             SendMessage(g_hwndTBar, TB_SETSTATE, IDM_STEP_FWD, MAKELONG(TBSTATE_INDETERMINATE, 0L));
  1051.             SendMessage(g_hwndTBar, TB_SETSTATE, IDM_STEP_REV, MAKELONG(TBSTATE_INDETERMINATE, 0L));
  1052.             break;
  1053.  
  1054.         case IDM_PLAY_FAST_REV :
  1055.             // all graphs just rewind the tape & update the toolbar
  1056.             DV_PutVcrMode(ED_MODE_PLAY_FASTEST_REV);
  1057.             SendMessage(g_hwndTBar, TB_SETSTATE, IDM_STEP_FWD, MAKELONG(TBSTATE_INDETERMINATE, 0L));
  1058.             SendMessage(g_hwndTBar, TB_SETSTATE, IDM_STEP_REV, MAKELONG(TBSTATE_INDETERMINATE, 0L));
  1059.             break;            
  1060.  
  1061.         case IDM_STEP_FWD :
  1062.             // all graphs just forward the tape & update the toolbar
  1063.             DV_PutVcrMode(ED_MODE_STEP_FWD);
  1064.             g_bUseAtnTimer = FALSE;
  1065.             DV_DisplayTimecode();
  1066.             break;
  1067.  
  1068.         case IDM_STEP_REV :
  1069.             // all graphs just rewind the tape & update the toolbar
  1070.             DV_PutVcrMode(ED_MODE_STEP_REV);
  1071.             g_bUseAtnTimer = FALSE;
  1072.             DV_DisplayTimecode();
  1073.             break;
  1074.  
  1075.         case IDM_SEEKTIMECODE :
  1076.             // ATN Seek & display on the toolbar
  1077.              DV_SeekATN();
  1078.              DV_DisplayTimecode();
  1079.              break;
  1080.  
  1081.         } // switch (LOWORD(wParam))
  1082.     } // switch (iMsg)
  1083. }
  1084.  
  1085.  
  1086. void Mark_GraphMode_Menu(HWND hwnd, int idmVal)
  1087. {
  1088.     //uncheck everything first
  1089.     CheckMenuItem(g_hmenu, IDM_PREVIEW, MF_UNCHECKED);
  1090.     CheckMenuItem(g_hmenu, IDM_FILETODV, MF_UNCHECKED);
  1091.     CheckMenuItem(g_hmenu, IDM_DVTOFILE, MF_UNCHECKED);
  1092.     CheckMenuItem(g_hmenu, IDM_FILETODV_NOPRE, MF_UNCHECKED);
  1093.     CheckMenuItem(g_hmenu, IDM_DVTOFILE_NOPRE, MF_UNCHECKED);
  1094.  
  1095.     CheckMenuItem(g_hmenu, IDM_FILETODV_TYPE2, MF_UNCHECKED);
  1096.     CheckMenuItem(g_hmenu, IDM_FILETODV_NOPRE_TYPE2, MF_UNCHECKED);
  1097.     CheckMenuItem(g_hmenu, IDM_DVTOFILE_TYPE2, MF_UNCHECKED);
  1098.     CheckMenuItem(g_hmenu, IDM_DVTOFILE_NOPRE_TYPE2, MF_UNCHECKED);
  1099.  
  1100.     // check the selected graph mode
  1101.     CheckMenuItem(g_hmenu, idmVal, MF_CHECKED);
  1102. }
  1103.  
  1104. void Mark_ToolBar_Button(BOOL bEnableRecord, BOOL bEnableOthers)
  1105. {
  1106.     if(bEnableRecord == TRUE)
  1107.     {
  1108.         SendMessage(g_hwndTBar, TB_SETSTATE, IDM_RECORD, MAKELONG(TBSTATE_ENABLED, 0L));
  1109.     }
  1110.     else
  1111.         SendMessage(g_hwndTBar, TB_SETSTATE, IDM_RECORD, MAKELONG(TBSTATE_INDETERMINATE, 0L));
  1112.  
  1113.     if(bEnableOthers == TRUE)
  1114.     {
  1115.        //re-enable everything 
  1116.         SendMessage(g_hwndTBar, TB_SETSTATE, IDM_STEP_REV, MAKELONG(TBSTATE_ENABLED, 0L));
  1117.         SendMessage(g_hwndTBar, TB_SETSTATE, IDM_REW, MAKELONG(TBSTATE_ENABLED, 0L));
  1118.         SendMessage(g_hwndTBar, TB_SETSTATE, IDM_PLAY_FAST_REV, MAKELONG(TBSTATE_ENABLED, 0L));
  1119.         SendMessage(g_hwndTBar, TB_SETSTATE, IDM_PLAY_FAST_FF, MAKELONG(TBSTATE_ENABLED, 0L));
  1120.         SendMessage(g_hwndTBar, TB_SETSTATE, IDM_FF, MAKELONG(TBSTATE_ENABLED, 0L));
  1121.         SendMessage(g_hwndTBar, TB_SETSTATE, IDM_STEP_FWD, MAKELONG(TBSTATE_ENABLED, 0L));
  1122.         SendMessage(g_hwndTBar, TB_SETSTATE, IDM_SEEKTIMECODE, MAKELONG(TBSTATE_ENABLED, 0L));
  1123.     }
  1124.     else
  1125.     {
  1126.         //disable everything except for play, pause, and stop
  1127.         SendMessage(g_hwndTBar, TB_SETSTATE, IDM_STEP_REV, MAKELONG(TBSTATE_INDETERMINATE, 0L));
  1128.         SendMessage(g_hwndTBar, TB_SETSTATE, IDM_REW, MAKELONG(TBSTATE_INDETERMINATE, 0L));
  1129.         SendMessage(g_hwndTBar, TB_SETSTATE, IDM_PLAY_FAST_REV, MAKELONG(TBSTATE_INDETERMINATE, 0L));
  1130.         SendMessage(g_hwndTBar, TB_SETSTATE, IDM_PLAY_FAST_FF, MAKELONG(TBSTATE_INDETERMINATE, 0L));
  1131.         SendMessage(g_hwndTBar, TB_SETSTATE, IDM_FF, MAKELONG(TBSTATE_INDETERMINATE, 0L));
  1132.         SendMessage(g_hwndTBar, TB_SETSTATE, IDM_STEP_FWD, MAKELONG(TBSTATE_INDETERMINATE, 0L));
  1133.         SendMessage(g_hwndTBar, TB_SETSTATE, IDM_SEEKTIMECODE, MAKELONG(TBSTATE_INDETERMINATE, 0L));
  1134.     }
  1135. }
  1136.  
  1137. void GetSelectedGraphMode( WPARAM wParam, GRAPH_TYPE* pGraphType)
  1138. {
  1139.     switch (LOWORD (wParam))
  1140.     {  
  1141.         case IDM_PREVIEW :
  1142.             *pGraphType = GRAPH_PREVIEW;
  1143.             break;
  1144.         case IDM_FILETODV :
  1145.             *pGraphType = GRAPH_FILE_TO_DV;
  1146.             break;
  1147.         case IDM_FILETODV_NOPRE :
  1148.             *pGraphType = GRAPH_FILE_TO_DV_NOPRE;
  1149.             break;
  1150.         case IDM_DVTOFILE :
  1151.             *pGraphType = GRAPH_DV_TO_FILE;
  1152.             break;
  1153.         case IDM_DVTOFILE_NOPRE :
  1154.             *pGraphType = GRAPH_DV_TO_FILE_NOPRE;
  1155.             break;
  1156.         case IDM_FILETODV_TYPE2 :
  1157.             *pGraphType = GRAPH_FILE_TO_DV_TYPE2;
  1158.             break;
  1159.         case IDM_FILETODV_NOPRE_TYPE2 :
  1160.             *pGraphType = GRAPH_FILE_TO_DV_NOPRE_TYPE2;
  1161.             break;
  1162.         case IDM_DVTOFILE_TYPE2 :
  1163.             *pGraphType = GRAPH_DV_TO_FILE_TYPE2;
  1164.             break;
  1165.         case IDM_DVTOFILE_NOPRE_TYPE2 :
  1166.             *pGraphType = GRAPH_DV_TO_FILE_NOPRE_TYPE2;
  1167.             break;
  1168.     }
  1169. }
  1170.  
  1171. /*-------------------------------------------------------------------------
  1172. Routine:        SetPreviewWindow
  1173. Purpose:        Hooks up stream  *from camera* to preview window
  1174.                     Note that the preview for the playback from the file is handled within DV_MakeFileToDvGraph() stuff
  1175. Arguments:    None
  1176. Returns:        HRESULT as appropriate
  1177. Notes:          
  1178. ------------------------------------------------------------------------*/
  1179. HRESULT SetPreviewWindow(void)
  1180. {
  1181.     HRESULT hr = S_OK;
  1182.  
  1183.     ASSERT(g_pGraph->m_pVideoWindow!= NULL);
  1184.  
  1185.     //Set the video window.
  1186.     hr = g_pGraph->m_pVideoWindow->put_Owner((OAHWND)g_hwndApp);     // We own the window now
  1187.     if(FAILED(hr))
  1188.     {
  1189.         return hr;
  1190.     }
  1191.  
  1192.     // you are now a child
  1193.     hr = g_pGraph->m_pVideoWindow->put_WindowStyle(WS_CHILD| WS_CLIPSIBLINGS);     
  1194.     if(FAILED(hr))
  1195.     {
  1196.         return hr;
  1197.     }
  1198.  
  1199.     // give the preview window all our space but where the tool bar and status bar are        
  1200.     RECT clientRect, toolbarRect;
  1201.     GetClientRect(g_hwndApp, &clientRect);
  1202.     GetWindowRect(g_hwndTBar, &toolbarRect);
  1203.  
  1204.    // g_pGraph->m_pVideoWindow->SetWindowPosition(0, toolbarRect.bottom - toolbarRect.top, clientRect.right, clientRect.bottom);
  1205.     g_pGraph->m_pVideoWindow->SetWindowPosition(0, toolbarRect.bottom - toolbarRect.top, g_iVWWidth, g_iVWHeight);
  1206.  
  1207.     hr = g_pGraph->m_pVideoWindow->put_Visible(OATRUE);
  1208.     if(FAILED(hr))
  1209.     {
  1210.         return hr;
  1211.     }
  1212.  
  1213.     return hr;
  1214.  
  1215. /*-------------------------------------------------------------------------
  1216. Routine:        DV_DroppedFrameProc
  1217. Purpose:        Callback proc to display dropped frame info
  1218. Arguments:    DWORD current time
  1219. Returns:        None
  1220. Notes:          For both Capture & Transmit graphs
  1221. ------------------------------------------------------------------------*/
  1222. void CALLBACK DV_DroppedFrameProc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime)
  1223. {
  1224.     HRESULT hr = S_OK;
  1225.     long dropped = 0, notdropped = 0;
  1226.     TCHAR buffer[128];
  1227.     DWORD time = dwTime - g_CapStartTime;
  1228.  
  1229.     BOOL bIsModeTransmit = TRUE;      
  1230.     hr = g_pGraph->getDroppedFrameNum( &bIsModeTransmit, &dropped, ¬dropped);
  1231.     if(FAILED(hr))
  1232.     {
  1233.         DV_StatusText(TEXT("Cannot report dropped frame information"), 1);
  1234.         KillTimer(hwnd, DV_TIMER_FRAMES);
  1235.     }
  1236.  
  1237.     if( bIsModeTransmit == FALSE)
  1238.         wsprintf(buffer, TEXT("Captured %d frames (%d dropped) %d.%d sec."), notdropped, dropped, time / 1000, time / 100 - time / 1000 * 10);
  1239.     else
  1240.         wsprintf(buffer, TEXT("Transmitted %d frames (%d dropped) %d.%d sec."), notdropped, dropped, time / 1000, time / 100 - time / 1000 * 10);
  1241.  
  1242.     DV_StatusText(buffer, 1);
  1243.  
  1244. /*-------------------------------------------------------------------------
  1245. Routine:        DV_TimecodeTimerProc
  1246. Purpose:        Callback function for the timer proc
  1247. Arguments:    Usual Timer Processing Parameters
  1248. Returns:        None
  1249. Notes:          
  1250. ------------------------------------------------------------------------*/
  1251. void CALLBACK DV_TimecodeTimerProc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime)
  1252. {
  1253.     DV_DisplayTimecode();
  1254.  
  1255. /*-------------------------------------------------------------------------
  1256. Routine:        DV_DisplayTimecode
  1257. Purpose:        Routine to display timecodes
  1258. Arguments:    None
  1259. Returns:        None
  1260. Notes:          This is TimeCode Read not Absolute Track Number Read
  1261. ------------------------------------------------------------------------*/
  1262. void DV_DisplayTimecode(void)
  1263. {
  1264.     TIMECODE_SAMPLE TimecodeSample;
  1265.     TimecodeSample.timecode.dwFrames = 0;
  1266.     static DWORD i1 = 0, i2 = 0, i3 = 0;
  1267.  
  1268.     TimecodeSample.dwFlags = ED_DEVCAP_TIMECODE_READ;
  1269.  
  1270.     // Query the TimeCode sample data
  1271.     HRESULT hr = g_pGraph->m_pIAMTCReader->GetTimecode(&TimecodeSample);
  1272.     if(FAILED(hr))
  1273.     {
  1274.         //MBOX(TEXT("DV_DisplayTimecode::g_pGraph->m_pIAMTCReader->GetTimecode() failed"));
  1275.     }
  1276.     TCHAR szBuf[4];
  1277.   
  1278.     // It's worth it to spend a few extra cycles, and to store the static variables
  1279.     // to avoid calling wsprintf and setwindowtext on every timer tick.
  1280.     if (i1 != (TimecodeSample.timecode.dwFrames & 0xff000000) >> 24)
  1281.     {
  1282.         wsprintf(szBuf, TEXT("%.2x"),((TimecodeSample.timecode.dwFrames & 0xff000000) >> 24));
  1283.         SetDlgItemText(g_hwndTBar, IDC_EDIT_HOUR, szBuf);
  1284.     } 
  1285.     i1 = (TimecodeSample.timecode.dwFrames & 0xff000000) >> 24;
  1286.  
  1287.     if (i2 != (TimecodeSample.timecode.dwFrames & 0x00ff0000) >> 16)
  1288.     {
  1289.         wsprintf(szBuf, TEXT("%.2x"),((TimecodeSample.timecode.dwFrames & 0x00ff0000) >> 16));
  1290.         SetDlgItemText(g_hwndTBar, IDC_EDIT_MINUTE, szBuf);
  1291.     } 
  1292.     i2 = (TimecodeSample.timecode.dwFrames & 0x00ff0000) >> 16;
  1293.     
  1294.     if (i3 != (TimecodeSample.timecode.dwFrames & 0x0000ff00) >>  8)
  1295.     {
  1296.         wsprintf(szBuf, TEXT("%.2x"),((TimecodeSample.timecode.dwFrames & 0x0000ff00) >>  8));
  1297.         SetDlgItemText(g_hwndTBar, IDC_EDIT_SECOND, szBuf);
  1298.     } 
  1299.     i3 = (TimecodeSample.timecode.dwFrames & 0x0000ff00) >>  8;
  1300.  
  1301.     wsprintf(szBuf, TEXT("%.2x"),(TimecodeSample.timecode.dwFrames & 0x000000ff));
  1302.     SetDlgItemText(g_hwndTBar, IDC_EDIT_FRAME, szBuf); 
  1303.  
  1304. /*-------------------------------------------------------------------------
  1305. Routine:      DV_SeekATN
  1306. Purpose:      ATN Seek function - uses GetTransportBasicParameters to send RAW AVC command 
  1307. Arguments:    None
  1308. Returns:      TRUE if successful
  1309. Notes:        This is Absolute Track Number Seek not TimeCode Seek but uses the timecode display as input
  1310. ------------------------------------------------------------------------*/
  1311. BOOL DV_SeekATN(void)
  1312. {
  1313.     BOOL bStatus = FALSE;
  1314.     HRESULT hr = S_OK;
  1315.     int iHr, iMn, iSc, iFr;
  1316.     //get the values from the edit fields
  1317.     iHr = GetDlgItemInt(g_hwndTBar, IDC_EDIT_HOUR,   &bStatus, FALSE);
  1318.     iMn = GetDlgItemInt(g_hwndTBar, IDC_EDIT_MINUTE, &bStatus, FALSE);
  1319.     iSc = GetDlgItemInt(g_hwndTBar, IDC_EDIT_SECOND, &bStatus, FALSE);
  1320.     iFr = GetDlgItemInt(g_hwndTBar, IDC_EDIT_FRAME,  &bStatus, FALSE);
  1321.  
  1322.     hr = g_pGraph->SeekATN( iHr, iMn, iSc, iFr );
  1323.     if(FAILED(hr))
  1324.     {
  1325.         MBOX(TEXT("Invalid Parameter - Time entered should be:\nHour:Minute:Second:Frame"));
  1326.         bStatus = FALSE;
  1327.     }
  1328.  
  1329.     return bStatus;
  1330.  
  1331. /*-------------------------------------------------------------------------
  1332. Routine:        DV_UpdateTapeInfo
  1333. Purpose:        Get Frame rate and availability of dvcr tape
  1334. Arguments:    None
  1335. Returns:        HRESULT as appropriate
  1336. Notes:          
  1337. ------------------------------------------------------------------------*/
  1338. BOOL DV_UpdateTapeInfo(void)
  1339. {
  1340.    //check information about the tape
  1341.     if (S_OK != g_pGraph->GetTapeInfo())
  1342.     {
  1343.         MBOX(TEXT("Tape is not inserted, or has an improper format.\nReinsert the tape and select Options - Check Tape"));
  1344.         DV_StatusText(TEXT("VCR Mode - No tape, or unknown format"), 2);
  1345.         return FALSE;
  1346.     } 
  1347.     else
  1348.     {
  1349.         switch(g_pGraph->m_VideoFormat)
  1350.         {
  1351.             case DVENCODERVIDEOFORMAT_NTSC:
  1352.                 DV_StatusText(TEXT("VCR Mode - NTSC"), 2);
  1353.                 break;
  1354.             case DVENCODERVIDEOFORMAT_PAL:
  1355.                 DV_StatusText(TEXT("VCR Mode - PAL"), 2);
  1356.                 break;
  1357.             default:
  1358.                 MBOX(TEXT("Unsupported or unrecognized tape format type"));
  1359.                 break;
  1360.         }
  1361.     }
  1362.  
  1363.     return TRUE;
  1364. }
  1365.  
  1366. /*-------------------------------------------------------------------------
  1367. Routine:        DV_RefreshMode
  1368. Purpose:        Use this to rebuild the necessary stuff to switch between VCR and camera mode
  1369. Arguments:    None
  1370. Returns:        TRUE if successful
  1371. Notes:          
  1372. ------------------------------------------------------------------------*/
  1373. BOOL DV_RefreshMode(void)
  1374. {
  1375.     BOOL bStatus    = FALSE;
  1376.  
  1377.     // Query the current device type
  1378.     DV_MODE SubunitMode;
  1379.     g_pGraph->GetDVMode( &SubunitMode );
  1380.     switch(SubunitMode)
  1381.     {
  1382.         case CameraMode :
  1383.             // update the Graph Mode menu items & status window
  1384.             EnableMenuItem(GetMenu(g_hwndApp), IDM_FILETODV, MF_GRAYED);
  1385.             EnableMenuItem(GetMenu(g_hwndApp), IDM_FILETODV_NOPRE, MF_GRAYED);
  1386.             EnableMenuItem(GetMenu(g_hwndApp), IDM_FILETODV_TYPE2, MF_GRAYED);
  1387.             EnableMenuItem(GetMenu(g_hwndApp), IDM_FILETODV_NOPRE_TYPE2, MF_GRAYED);
  1388.             EnableMenuItem(GetMenu(g_hwndApp), IDM_CHECKTAPE, MF_GRAYED);
  1389.             DV_StatusText(TEXT("Camera Mode"), 2);
  1390.             bStatus = TRUE;
  1391.             break;
  1392.  
  1393.         case VcrMode :
  1394.             // Query the tape info & update the status bar
  1395.             DV_UpdateTapeInfo();  
  1396.             // update the Graph Mode menu items & status window
  1397.             EnableMenuItem(GetMenu(g_hwndApp), IDM_CHECKTAPE, MF_ENABLED);
  1398.             EnableMenuItem(GetMenu(g_hwndApp), IDM_FILETODV, MF_ENABLED);
  1399.             EnableMenuItem(GetMenu(g_hwndApp), IDM_FILETODV_NOPRE, MF_ENABLED);
  1400.             EnableMenuItem(GetMenu(g_hwndApp), IDM_FILETODV_TYPE2, MF_ENABLED);
  1401.             EnableMenuItem(GetMenu(g_hwndApp), IDM_FILETODV_NOPRE_TYPE2, MF_ENABLED);
  1402.             EnableMenuItem(GetMenu(g_hwndApp), IDM_CHECKTAPE, MF_ENABLED);
  1403.             bStatus = TRUE;
  1404.             break;
  1405.  
  1406.         case UnknownMode :
  1407.                 MBOX(TEXT("Cannot determine camera / Vcr mode"));
  1408.                 DV_StatusText(TEXT("Unknown Mode"), 2);            
  1409.                 break;
  1410.             
  1411.         default :
  1412.                MBOX(TEXT("Bad return value from DV_RefreshMode"));
  1413.                break;
  1414.     }
  1415.  
  1416.     return bStatus;
  1417.  
  1418. /*-------------------------------------------------------------------------
  1419. Routine:        DV_CapSizeDlgProc
  1420. Purpose:        Dialog proc for cap size dialog
  1421. Arguments:    Usual Dialog Processing parameters
  1422. Returns:        BOOL
  1423. Notes:          
  1424. ------------------------------------------------------------------------*/
  1425. BOOL CALLBACK DV_CapSizeDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  1426. {
  1427.     switch ( msg )
  1428.     {
  1429.         case WM_INITDIALOG:
  1430.         {
  1431.             TCHAR           capDisk[8];
  1432.             ULARGE_INTEGER  ulFreeBytes;
  1433.             ULARGE_INTEGER  ulTotalBytes;
  1434.             ULARGE_INTEGER  ulAvailBytes;
  1435.  
  1436.             // make sure output file name has been input for capture
  1437.             if (!g_OutputFileName[0])
  1438.             {
  1439.                 MBOX(TEXT("Please set up an output file name for recording"));
  1440.                 EndDialog(hwnd, FALSE);
  1441.                 return FALSE;
  1442.             } 
  1443.  
  1444.             //need to determine disk space and init the dialog appropriately
  1445.             lstrcpyn(capDisk, g_OutputFileName, 3);
  1446.             capDisk[4] = '\0';
  1447.             GetDiskFreeSpaceEx(capDisk, &ulFreeBytes, &ulTotalBytes, &ulAvailBytes);
  1448.             //Dump1(TEXT("Available MB on drive %s is %d MB"), capDisk, ulAvailBytes.QuadPart / (1024 * 1024));
  1449.  
  1450.             //let's see what our top limits are, and set our limits appropriately
  1451.             if ((ulAvailBytes.QuadPart / DV_BYTES_IN_MEG) < 120)
  1452.             {
  1453.                 //less than 120 MB available - subtract 10 MB at a time until we get a usable amount
  1454.                 UINT i = 110;
  1455.                 while ((ulAvailBytes.QuadPart / DV_BYTES_IN_MEG) < i)
  1456.                 {
  1457.                     i -= 10;
  1458.                 } 
  1459.                 SendMessage(GetDlgItem(hwnd, IDC_SPIN_TIME), UDM_SETRANGE, 0, MAKELONG(i / 4, 1));
  1460.                 SendMessage(GetDlgItem(hwnd, IDC_SPIN_SIZE), UDM_SETRANGE, 0, MAKELONG(i, 1));
  1461.             }
  1462.             else
  1463.             {
  1464.                 SendMessage(GetDlgItem(hwnd, IDC_SPIN_TIME), UDM_SETRANGE, 0, MAKELONG( ((ulAvailBytes.QuadPart / (1024 * 1024) ) - 10) / 4, 1));
  1465.                 SendMessage(GetDlgItem(hwnd, IDC_SPIN_SIZE), UDM_SETRANGE, 0, MAKELONG( (ulAvailBytes.QuadPart / (1024 * 1024) ) - 10, 1));
  1466.             }
  1467.  
  1468.             //enable / disable the controls as appropriate
  1469.             switch (g_dwCaptureLimit)
  1470.             {
  1471.                 case DV_CAPLIMIT_NONE :
  1472.                     Button_SetCheck(GetDlgItem(hwnd, IDC_RADIO_NOLIMIT), TRUE);
  1473.                     EnableWindow(GetDlgItem(hwnd, IDC_EDIT_SIZE), FALSE);
  1474.                     EnableWindow(GetDlgItem(hwnd, IDC_SPIN_SIZE), FALSE);
  1475.                     EnableWindow(GetDlgItem(hwnd, IDC_EDIT_TIME), FALSE);
  1476.                     EnableWindow(GetDlgItem(hwnd, IDC_SPIN_TIME), FALSE);
  1477.                     break;
  1478.                 
  1479.                 case DV_CAPLIMIT_TIME :
  1480.                 {
  1481.                     /*check the radio button, disable the size based controls */
  1482.                     Button_SetCheck(GetDlgItem(hwnd, IDC_RADIO_TIME), TRUE);
  1483.                     EnableWindow(GetDlgItem(hwnd, IDC_EDIT_SIZE), FALSE);
  1484.                     EnableWindow(GetDlgItem(hwnd, IDC_SPIN_SIZE), FALSE);
  1485.  
  1486.                     break;
  1487.                 }
  1488.                 case DV_CAPLIMIT_SIZE :
  1489.                 {
  1490.                     /*check the radio button, disable the time based controls */
  1491.                     Button_SetCheck(GetDlgItem(hwnd, IDC_RADIO_SIZE), TRUE);
  1492.                     EnableWindow(GetDlgItem(hwnd, IDC_EDIT_TIME), FALSE);
  1493.                     EnableWindow(GetDlgItem(hwnd, IDC_SPIN_TIME), FALSE);
  1494.                     
  1495.                     break;                    
  1496.                 }
  1497.             }
  1498.             SetDlgItemInt(hwnd, IDC_EDIT_TIME, g_dwTimeLimit, FALSE);
  1499.             SetDlgItemInt(hwnd, IDC_EDIT_SIZE, g_dwDiskSpace, FALSE);
  1500.             break;
  1501.         } 
  1502.         case WM_COMMAND :
  1503.             switch LOWORD(wParam)
  1504.             {
  1505.                 // Update the controls ui according to the choices made
  1506.                 case IDC_RADIO_NOLIMIT :
  1507.                 {
  1508.                     Button_SetCheck(GetDlgItem(hwnd, IDC_RADIO_NOLIMIT), TRUE);
  1509.                     EnableWindow(GetDlgItem(hwnd, IDC_EDIT_SIZE), FALSE);
  1510.                     EnableWindow(GetDlgItem(hwnd, IDC_SPIN_SIZE), FALSE);
  1511.                     EnableWindow(GetDlgItem(hwnd, IDC_EDIT_TIME), FALSE);
  1512.                     EnableWindow(GetDlgItem(hwnd, IDC_SPIN_TIME), FALSE);
  1513.                     break;
  1514.                 }
  1515.                     
  1516.                 case IDC_RADIO_TIME :
  1517.                 {
  1518.                     Button_SetCheck(GetDlgItem(hwnd, IDC_RADIO_TIME), TRUE);
  1519.                     EnableWindow(GetDlgItem(hwnd, IDC_EDIT_SIZE), FALSE);
  1520.                     EnableWindow(GetDlgItem(hwnd, IDC_SPIN_SIZE), FALSE);
  1521.                     EnableWindow(GetDlgItem(hwnd, IDC_EDIT_TIME), TRUE);
  1522.                     EnableWindow(GetDlgItem(hwnd, IDC_SPIN_TIME), TRUE);
  1523.                     break;
  1524.                 } 
  1525.                 
  1526.                 case IDC_RADIO_SIZE :
  1527.                 {
  1528.                     Button_SetCheck(GetDlgItem(hwnd, IDC_RADIO_SIZE), TRUE);
  1529.                     EnableWindow(GetDlgItem(hwnd, IDC_EDIT_TIME), FALSE);
  1530.                     EnableWindow(GetDlgItem(hwnd, IDC_SPIN_TIME), FALSE);
  1531.                     EnableWindow(GetDlgItem(hwnd, IDC_EDIT_SIZE), TRUE);
  1532.                     EnableWindow(GetDlgItem(hwnd, IDC_SPIN_SIZE), TRUE);
  1533.                     break;
  1534.                 } 
  1535.  
  1536.                 case IDOK :
  1537.                 {
  1538.                     BOOL bTranslated = FALSE;
  1539.                     // The selections are made
  1540.                     // update the new global capture flag
  1541.                     if (Button_GetCheck(GetDlgItem(hwnd, IDC_RADIO_NOLIMIT)))
  1542.                     {
  1543.                         g_dwCaptureLimit = DV_CAPLIMIT_NONE;
  1544.                         //DV_LogOut(LOG_PRIORITY_INFO, LOG_LEVEL_MEDIUM, TEXT("No capture size limit"));
  1545.                     } 
  1546.                     else if (Button_GetCheck(GetDlgItem(hwnd, IDC_RADIO_TIME)))   
  1547.                     {
  1548.                         g_dwTimeLimit = GetDlgItemInt(hwnd, IDC_EDIT_TIME, &bTranslated, FALSE);
  1549.                         g_dwCaptureLimit = DV_CAPLIMIT_TIME;
  1550.                         //DV_LogOut(LOG_PRIORITY_INFO, LOG_LEVEL_MEDIUM, TEXT("Time based limit - %d"), g_dwTimeLimit);
  1551.                     } 
  1552.                     else if (Button_GetCheck(GetDlgItem(hwnd, IDC_RADIO_SIZE)))   
  1553.                     {
  1554.                         g_dwDiskSpace = GetDlgItemInt(hwnd, IDC_EDIT_SIZE, &bTranslated, FALSE);
  1555.                         g_dwCaptureLimit = DV_CAPLIMIT_SIZE;
  1556.                         //DV_LogOut(LOG_PRIORITY_INFO, LOG_LEVEL_MEDIUM, TEXT("Disk based limit - %d MB"), g_dwDiskSpace);
  1557.                     } 
  1558.                     EndDialog(hwnd, TRUE);
  1559.                     return TRUE;
  1560.                 }
  1561.                 
  1562.                 case IDCANCEL :
  1563.                     // update nothing much
  1564.                     EndDialog(hwnd, FALSE);
  1565.                     return FALSE;
  1566.                 default :
  1567.                     return FALSE;
  1568.             }            
  1569.             return TRUE;
  1570.     }
  1571.     return FALSE;
  1572. }
  1573.  
  1574. /*-------------------------------------------------------------------------
  1575. Routine:        DV_StopRecProc
  1576. Purpose:        Callback to stop recording after a specified time
  1577. Arguments:    Usual Timer Processing Parameters
  1578. Returns:        None
  1579. Notes:          
  1580. ------------------------------------------------------------------------*/
  1581. void CALLBACK DV_StopRecProc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime)
  1582. {
  1583.     SendMessage(g_hwndApp, WM_COMMAND, IDM_STOP, 0);
  1584.  
  1585. /*-------------------------------------------------------------------------
  1586. Routine:        DV_AboutDlgProc
  1587. Purpose:        simple standard about dialog box proc 
  1588. Arguments:    Usual Dialog Processing parameters
  1589. Returns:        BOOL
  1590. Notes:          
  1591. ------------------------------------------------------------------------*/
  1592. BOOL CALLBACK DV_AboutDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  1593. {
  1594.     switch ( msg )
  1595.     {
  1596.     //the only command we process are those that close the dialog   
  1597.         case WM_COMMAND:
  1598.             EndDialog(hwnd, TRUE);
  1599.             return TRUE;
  1600.         case WM_INITDIALOG:
  1601.             return TRUE;
  1602.     }
  1603.  
  1604.     return FALSE;
  1605. }